package com.itheima.reggie.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPay;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.R;
import com.itheima.reggie.config.MyConfig;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.*;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ShoppingCartMapper shoppingCartMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AddressBookMapper addressBookMapper;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    //todo 提交订单
    @Override
    public R submit(Orders orders) {
        //A. 获得当前用户id, 查询当前用户的购物车数据
        Long userId = BaseContext.threadLocal.get();
        LambdaQueryWrapper<ShoppingCart> cartWrapper = new LambdaQueryWrapper<>();
        cartWrapper.eq(ShoppingCart::getUserId,userId);
        //订单明细数据
        List<ShoppingCart> shoppingCarts = shoppingCartMapper.selectList(cartWrapper);
        //B. 根据当前登录用户id, 查询用户数据
        User user = userMapper.selectById(userId);
        //C. 根据地址ID, 查询地址数据
        AddressBook addressBook = addressBookMapper.selectById(orders.getAddressBookId());
        //D. 组装订单数据, 批量保存订单数据
        orders.setStatus(1);//待付款
        orders.setUserId(userId);
        orders.setAddress(addressBook.getDetail());//收货人地址
        orders.setAmount(sunMoney(shoppingCarts));//计算获得金额
        orders.setCheckoutTime(LocalDateTime.now());//付款时间
        orders.setConsignee(addressBook.getConsignee());//收件人名字
        orders.setOrderTime(LocalDateTime.now());//下单时间
        orders.setPayMethod(1);//支付方式
        orders.setNumber(UUID.randomUUID().toString());//商品订单号
        orders.setPhone(addressBook.getPhone());
        //orders.setRemark();//配置前端传输
        orders.setUserName(user.getName());//登录的用户名字
        orderMapper.insert(orders);
        //E. 组装订单明细数据, 批量保存订单明细
        String s = JSON.toJSONString(shoppingCarts);
        List<OrderDetail> orderDetails = JSON.parseArray(s, OrderDetail.class);
        //orders.setSumNum(orderDetails.size());
        orderDetails.stream().forEach(c->{
            c.setOrderId(orders.getId());
        });
        //F. 删除当前用户的购物车列表数据
        orderDetailService.saveBatch(orderDetails);
        shoppingCartService.clean();

        //todo 请求微信获得支付的二维码信息
        //1.创建一个微信支付核心对象
        MyConfig mc = new MyConfig();
        //CONFIG配置类
        WXPay wxPay = null;//wxPay核心支付类
        try {
            wxPay = new WXPay(mc);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3.可以进行微信支付接口的调用了
        //统一下单接口
        //4.wxPay.unifiedOrder(); = 调用微信的支付接口  参数map
        HashMap<String, String> map = new HashMap<>();
        //封装请求参数
        //购买的商品信息
        map.put("body","红烧肉套餐");//商品描述
        //商家的订单号
        map.put("out_trade_no",orders.getId()+"");//商品描述  唯一
        //付款金额
        map.put("total_fee","1");//以分为单位  1分钱
        map.put("spbill_create_ip","127.0.0.1");//服务器地址
        //回调通知  商家接收微信的信息的接口
        map.put("notify_url","/wx/notify");//
        //支付类型
        map.put("trade_type","NATIVE");//支付方式
        //模拟浏览器发送一个http请求
        /**
         * requsetMap 代表请求参数
         * responseMap  返回值
         */
        try {
            Map<String, String> reponseMap = wxPay.unifiedOrder(map);
            map.put("out_trade_no",orders.getId()+"");//自己添加一个订单号
            return R.success(reponseMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回值中 code_url 就是支付二维码连接
        return R.error("下单失败");
    }

    //todo 查看个人中心
    @Override
    public R findPage(Integer page,Integer pageSize) {
        IPage<Orders> p = new Page<>();
        LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Orders::getUserId,BaseContext.threadLocal.get());
        wrapper.orderByDesc(Orders::getOrderTime);
        IPage<Orders> ordersPage = orderMapper.selectPage(p, wrapper);

        List<Orders> records = ordersPage.getRecords();
        String jsonString = JSON.toJSONString(records);
        List<OrdersDto> ordersDtos = JSON.parseArray(jsonString, OrdersDto.class);
        for (OrdersDto ordersDto : ordersDtos) {
            LambdaQueryWrapper<OrderDetail> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.eq(OrderDetail::getOrderId,ordersDto.getId());
            List<OrderDetail> orderDetails = orderDetailMapper.selectList(wrapper2);
            ordersDto.setOrderDetails(orderDetails);
        }

        String s = JSON.toJSONString(ordersPage);
        Page page1 = JSON.parseObject(s, Page.class);
        page1.setRecords(ordersDtos);
        return R.success(page1);
    }

    // todo 修改订单状态
    @Override
    public void updateStatus(String out_trade_no, String transaction_id) {
         //1.根据订单id  查询出订单对象
        Orders orders = orderMapper.selectById(out_trade_no);
        //2.修改订单状态并且存储流水号
        orders.setStatus(2);
        //3.保存到数据库
        orderMapper.updateById(orders);
    }

    //todo 累计计算订单总金额
    private BigDecimal sunMoney(List<ShoppingCart> shoppingCarts) {
        BigDecimal bigDecimal = new BigDecimal(0);
        for (ShoppingCart shoppingCart : shoppingCarts) {
            BigDecimal amount = shoppingCart.getAmount();
            BigDecimal bigDecimal1 = new BigDecimal(shoppingCart.getNumber());
            BigDecimal multiply = amount.multiply(bigDecimal1);
            bigDecimal=bigDecimal.add(multiply);
        }
        return bigDecimal;
    }
}